package algo;

import algo.BackTrackSearch.BackTrackSearch;
import algo.BackTrackSearch.SolutionTT;
import algo.Common.ClassTT;
import algo.Common.Course;
import algo.Common.Data;
import algo.Common.DataOut;
import algo.LocalSearch.TabuSearch;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.util.HashMap;
import java.util.List;
import java.util.Vector;
import vn.webapp.model.Classes;

public class appMain {

    /**
     * @param args
     */
    public void writeSolution(Data D, int[] sol_slots, int[] sol_days, String fn) {
        int minDay = D.getMinDay();
        int maxDay = D.getMaxDay();
        int nbClasses = D.getClasses().size();
        int nbCourses = D.getCourses().size();
        Course[] courses = new Course[nbCourses];
        HashMap hmap = new HashMap();
        for (int i = 0; i < nbCourses; i++) {
            courses[i] = D.getCourses().elementAt(i);
            hmap.put(courses[i], new Integer(i));
        }

        //write to file
        try {
            //BufferedWriter fo = new BufferedWriter(new FileWriter("timetabling.html"));
            BufferedWriter fo = new BufferedWriter(new FileWriter(fn));
            fo.write("<style type=" + '"' + "text/css" + '"' + ">\n");
            fo.write("table.timetabling_type {background-color:transparent;border-collapse:collapse;width:100%;}\n");
            fo.write("table.timetabling_type th, table.timetabling_type td {text-align:center;border:1px solid black;padding:5px;}\n");
            fo.write("table.timetabling_type th {background-color:AntiqueWhite;}\n");
            fo.write("table.timetabling_type td:first-child {width:20%;text-align:center;}\n");
            fo.write("</style>\n");

            fo.write("<table border=1, class=" + '"' + "timetabling_type" + '"' + ">\n");
            fo.write("<tr>\n");
            fo.write("<td> Lop </td>\n");
            for (int i = minDay; i <= maxDay; i++) {
                fo.write("<td colspan=" + '"' + "6" + '"' + "> Thu " + i + "</td>\n");
            }
            fo.write("</tr>\n");
            for (int i = 0; i <= nbClasses - 1; i++) {
                ClassTT cls = D.getClass(i);
                fo.write("<tr>\n");
                fo.write("<td>" + cls.getID() + "</td>\n");
                Vector<Course> coursesClass = D.getCoursesOfClass(cls);
                //writeLog("Class " + cls.getID() + "has " + coursesClass.size() + " courses\n");
                System.out.print("Class " + cls.getID() + " has " + coursesClass.size() + " courses: ");
                for (int j = 0; j < coursesClass.size(); j++) {
                    System.out.print(coursesClass.elementAt(j).getName() + "| ");
                }
                System.out.println("");
                //System.out.println("Class " + cls.getID());
                for (int d = minDay; d <= maxDay; d++) {
                    // find all courses allocated in day d
                    Vector<Integer> courseID = new Vector<Integer>();
                    for (int j = 0; j < coursesClass.size(); j++) {
                        Course c = coursesClass.elementAt(j);
                        Integer idx = (Integer) hmap.get(c);
                        //System.out.println("course " + c.getName() + " has idx = " + idx);
                        if (sol_days[idx] == d) {
                            courseID.add(idx);
                        }
                    }
                    //writeLog("Day d = " + d + "courses = (" + courseID.size() + "): ");
                    //System.out.print("Day d = " + d + ", courses = (" + courseID.size() + "): ");
                    int[] cid = new int[courseID.size()];
                    for (int j = 0; j < courseID.size(); j++) {
                        cid[j] = courseID.elementAt(j);
                        //System.out.print(cid[j] + " ");
                    }
                    //System.out.println("");
                    // sort id of courses of day d in an increasing order of slot
                    for (int i1 = 0; i1 < courseID.size() - 1; i1++) {
                        for (int i2 = i1 + 1; i2 < courseID.size(); i2++) {
                            if (sol_slots[cid[i1]] > sol_slots[cid[i2]]) {
                                int tg = cid[i1];
                                cid[i1] = cid[i2];
                                cid[i2] = tg;
                            }
                        }
                    }
                    for (int j = 0; j < courseID.size(); j++) {
                        System.out.print(cid[j] + "(" + sol_slots[cid[j]] + "," + courses[cid[j]].getNbrSlots() + ") ");
                    }
                    System.out.println("");

                    int span = 0;
                    if (courseID.size() <= 0) {
                        span = 6;
                        if (span > 0) {
                            fo.write("<td colspan=" + '"' + span + '"' + ">" + "x" + "</td>\n");
                        }
                        continue;
                    }
                    span = sol_slots[cid[0]] - 1;
                    if (span > 0) {
                        fo.write("<td colspan=" + '"' + span + '"' + ">" + "x" + "</td>\n");
                    }
                    for (int j = 0; j < courseID.size(); j++) {
                        span = courses[cid[j]].getNbrSlots();
                        int finish_slot = sol_slots[cid[j]] + courses[cid[j]].getNbrSlots() - 1;
                        if (span > 0) {
                            fo.write("<td colspan=" + '"' + span + '"' + ">" + "[" + courses[cid[j]].getID() + "] " + courses[cid[j]].getName()
                                    + " T(" + sol_slots[cid[j]] + "-" + finish_slot + ")" + "I(" + courses[cid[j]].getInstructor().getID() + ")" + "</td>\n");
                        }
                        if (j + 1 < courseID.size()) {
                            span = sol_slots[cid[j + 1]] - (sol_slots[cid[j]] + courses[cid[j]].getNbrSlots());
                            if (span > 0) {
                                fo.write("<td colspan=" + '"' + span + '"' + ">" + "x" + "</td>\n");
                            }
                        }
                    }
                    span = 6 + 1 - (sol_slots[cid[courseID.size() - 1]] + courses[cid[courseID.size() - 1]].getNbrSlots());
                    if (span > 0) {
                        fo.write("<td colspan=" + '"' + span + '"' + ">" + "x" + "</td>\n");
                    }
                }
                fo.write("</tr>\n");
                //break;
            }
            fo.write("</table>\n");
            fo.close();
            
        } catch (IOException e) {
            System.out.println("Cannot create result file result.html");
        }

    }
    
    public Vector<DataOut> vOutPutData(Data D, int[] sol_slots, int[] sol_days, List<Classes> __classes)
    {
        int minDay = D.getMinDay();
        int maxDay = D.getMaxDay();
        int nbClasses = D.getClasses().size();
        int nbCourses = D.getCourses().size();
        Vector<DataOut> _outPut = new Vector<DataOut>();
        List<Classes> __class__ = __classes;
        
        Course[] courses = new Course[nbCourses];
        HashMap hmap = new HashMap();
        for (int i = 0; i < nbCourses; i++) {
            courses[i] = D.getCourses().elementAt(i);
            hmap.put(courses[i], new Integer(i));
        }
        for (int i = 0; i <= nbClasses - 1; i++) {
            ClassTT cls = D.getClass(i);
            Vector<Course> coursesClass = D.getCoursesOfClass(cls);
            
            for (int d = minDay; d <= maxDay; d++) {
                // find all courses allocated in day d
                Vector<Integer> courseID = new Vector<Integer>();
                for (int j = 0; j < coursesClass.size(); j++) {
                    Course c = coursesClass.elementAt(j);
                    Integer idx = (Integer) hmap.get(c);
                    if (sol_days[idx] == d) {
                        courseID.add(idx);
                    }
                }
                int[] cid = new int[courseID.size()];
                for (int j = 0; j < courseID.size(); j++) {
                    cid[j] = courseID.elementAt(j);
                }
                for (int i1 = 0; i1 < courseID.size() - 1; i1++) {
                    for (int i2 = i1 + 1; i2 < courseID.size(); i2++) {
                        if (sol_slots[cid[i1]] > sol_slots[cid[i2]]) {
                            int tg = cid[i1];
                            cid[i1] = cid[i2];
                            cid[i2] = tg;
                        }
                    }
                }

                int span = 0;
                if (courseID.size() <= 0) {
                    span = 6;
                    if (span > 0) {
                        //fo.write("<td colspan=" + '"' + span + '"' + ">" + "x" + "</td>\n");
                    }
                    continue;
                }
                span = sol_slots[cid[0]] - 1;
                if (span > 0) {
                    //fo.write("<td colspan=" + '"' + span + '"' + ">" + "x" + "</td>\n");
                }
                for (int j = 0; j < courseID.size(); j++) {
                    span = courses[cid[j]].getNbrSlots();
                    int finish_slot = sol_slots[cid[j]] + courses[cid[j]].getNbrSlots() - 1;
                    if (span > 0) {
                        //fo.write("<td colspan=" + '"' + span + '"' + ">" + "[" + courses[cid[j]].getID() + "] " + courses[cid[j]].getName()
                        //+ " T(" + sol_slots[cid[j]] + "-" + finish_slot + ")" + "I(" + courses[cid[j]].getInstructor().getID() + ")" + "</td>\n");
                        // Set a temp for holding data
                        int _outClassId = 0;
                        int _outDayTime = d;
                        int _outCourseId = Integer.parseInt(courses[cid[j]].getID());
                        int _outSlot = sol_slots[cid[j]];
                        int _outInstructor = courses[cid[j]].getInstructor().getID();
                        int _outRoomId = d; 
                        int _outSessionId = 1;
                        String __name = null;
                        for(Classes clas_ : __class__)
                        {
                            __name = clas_.getCode();
                            
                            if(cls.getID().equals(clas_.getCode()))
                            {
                                _outClassId = clas_.getClass_id();
                                DataOut _tempData = new DataOut(_outClassId, _outDayTime, _outCourseId, _outSlot, _outInstructor, _outRoomId, _outSessionId);
                                _outPut.addElement(_tempData);
                            }
                        }
                        
//                        _tempData.setClassId(Integer.parseInt(cls.getID()));
//                        _tempData.setDayTime(d);
//                        _tempData.setCourseId(Integer.parseInt(courses[cid[j]].getID()));
//                        _tempData.setSlot(sol_slots[cid[j]]);
//                        _tempData.setTeacherId(courses[cid[j]].getInstructor().getID());
//                        _tempData.setRoomId(d);
//                        _tempData.setSessionId(1);
                        
                        
                    }
                    if (j + 1 < courseID.size()) {
                        span = sol_slots[cid[j + 1]] - (sol_slots[cid[j]] + courses[cid[j]].getNbrSlots());
                        if (span > 0) {
                            //fo.write("<td colspan=" + '"' + span + '"' + ">" + "x" + "</td>\n");
                        }
                    }
                }
                span = 6 + 1 - (sol_slots[cid[courseID.size() - 1]] + courses[cid[courseID.size() - 1]].getNbrSlots());
                if (span > 0) {
                    //fo.write("<td colspan=" + '"' + span + '"' + ">" + "x" + "</td>\n");
                }
            }
        }
        return _outPut;
    }

    public static void main(String args) {
        try {

            String content = "This is the content to write into file";

            File file = new File("filename.txt");

            // if file doesnt exists, then create it
            if (!file.exists()) {
                file.createNewFile();
            }

            FileWriter fw = new FileWriter(file.getAbsoluteFile());
            BufferedWriter bw = new BufferedWriter(fw);
            bw.write(content);
            bw.close();

            System.out.println("Done");

        } catch (IOException e) {
            e.printStackTrace();
        }
        // TODO Auto-generated method stub
        System.out.println("TimeTablingHUST");
        Data D = new Data();
        D.readData("timetabling-data.xml");
        //return;
        appMain m = new appMain();

        SolutionTT sol = new SolutionTT(1, 6, 2, 6);
        sol.init(D);
        BackTrackSearch s = new BackTrackSearch();
        s.search(sol, D);
        int[] sol_slots_bt = s.getSolutionSlots();
        int[] sol_days_bt = s.getSolutionDays();
        m.writeSolution(D, sol_slots_bt, sol_days_bt, "timetabling-backtrack.html");


//          2nd method
//        TabuSearch ts = new TabuSearch(D);
//        ts.localsearch(10000);
//        int[] sol_slots = ts.getSolutionSlots();
//        int[] sol_days = ts.getSolutionDays();
//
//
//        m.writeSolution(D, sol_slots, sol_days, "timetabling-tabu.html");
//
//        for (int i = 0; i < sol_slots.length; i++) {
//            //System.out.println("Course " + i + " slot = " + sol_slots[i] + " day = " + sol_days[i]);
//        }
        System.out.println("Finished");
    }
    
    public static String test()
    {
        try {
            Data D = new Data();
            D.readData("timetabling-data.xml");
            //return;
            appMain m = new appMain();

            SolutionTT sol = new SolutionTT(1, 6, 2, 6);
            sol.init(D);
            BackTrackSearch s = new BackTrackSearch();
            s.search(sol, D);
            int[] sol_slots_bt = s.getSolutionSlots();
            int[] sol_days_bt = s.getSolutionDays();
            m.writeSolution(D, sol_slots_bt, sol_days_bt, "timetabling-backtrack.html");
            return "Good job";
        } catch (Exception e) {
            String mes = e.getMessage();
            String mes1 = e.getLocalizedMessage();
            return mes.concat(mes1);
        }
        
    }
}
